package org.cleverframe.common.spring;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.stereotype.Service;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;

/**
 * 获取Spring ApplicationContext容器的类<br>
 * 1.以静态变量保存Spring ApplicationContext<br>
 * 2.可在任何代码任何地方任何时候取出ApplicaitonContext<br>
 * 3.提供获取Spring容器中的Bean的方法<br>
 * 
 * @author LiZW
 * @version 2015年5月28日 下午2:33:15
 */
@Service("springContextHolder")
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean
{
    private final static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class);

    /** Spring ApplicationContext容器 */
    private static ApplicationContext applicationContext = null;

    /** Spring WebApplicationContext容器，不能直接获取该属性，必须调用getter方法 */
    private static WebApplicationContext webApplicationContext = null;

    /**
     * 实现ApplicationContextAware接口, 注入Context到静态变量中.
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
    {
        if (SpringContextHolder.applicationContext != null)
        {
            logger.info("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
        }
        SpringContextHolder.applicationContext = applicationContext;
    }

    /**
     * 实现DisposableBean接口, 在Context关闭时清理静态变量.
     */
    @Override
    public void destroy() throws Exception
    {
        SpringContextHolder.clearHolder();
    }

    /**
     * 清除SpringContextHolder中的ApplicationContext为Null.
     */
    public static void clearHolder()
    {
        if (logger.isDebugEnabled())
        {
            logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
        }
        applicationContext = null;
    }

    /**
     * 获取Spring容器applicationContext对象
     * */
    public static ApplicationContext getApplicationContext()
    {
        return applicationContext;
    }
    
    /**
     * 获取Spring容器webApplicationContext对象
     * */
    @Deprecated
    public static WebApplicationContext getWebApplicationContext()
    {
        if (webApplicationContext == null)
        {
            webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        }
        return webApplicationContext;
    }
    
    /**
     * 获取系统根目录
     * */
    public static String getRootRealPath()
    {
        String rootRealPath = "";
        try
        {
            rootRealPath = applicationContext.getResource("").getFile().getAbsolutePath();
        }
        catch (IOException e)
        {
            logger.warn("获取系统根目录失败");
        }
        return rootRealPath;
    }

    /**
     * 获取资源根目录
     * */
    public static String getResourceRootRealPath()
    {
        String rootRealPath = "";
        try
        {
            rootRealPath = new DefaultResourceLoader().getResource("").getFile().getAbsolutePath();
        }
        catch (IOException e)
        {
            logger.warn("获取资源根目录失败");
        }
        return rootRealPath;
    }

    /**
     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name)
    {
        return (T) applicationContext.getBean(name);
    }

    /**
     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    public static <T> T getBean(Class<T> requiredType)
    {
        return applicationContext.getBean(requiredType);
    }

    /**
     * 从静态变量webApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @Deprecated
    @SuppressWarnings("unchecked")
    public static <T> T getWebBean(String name)
    {
        return (T) getWebApplicationContext().getBean(name);
    }

    /**
     * 从静态变量webApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @Deprecated
    public static <T> T getWebBean(Class<T> requiredType)
    {
        return getWebApplicationContext().getBean(requiredType);
    }
}
